import { useAddSignal } from "@/hooks/useSignal";
import { ViewportEffect } from "@/core/Viewport.Effect";
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass";
import * as THREE from "three";

export class ViewportSignals {
    private viewport: any;

    constructor(viewport) {
        this.viewport = viewport;

        this.init();
    }

    init() {
        useAddSignal("sceneGraphChanged", this.sceneGraphChanged.bind(this));
        useAddSignal("objectFocused", this.objectFocused.bind(this));
        useAddSignal("objectFocusedView", this.objectFocusedView.bind(this));
        useAddSignal("objectSelected", this.objectSelected.bind(this));
        useAddSignal("sceneResize", this.sceneResize.bind(this));
        useAddSignal("sceneLoadComplete", this.sceneLoadComplete.bind(this));
    }

    /**
     * 判断对象是否是可射线选中的
     */
    objectIsCanPick(object: THREE.Object3D) {
        return object !== null && object !== this.viewport.scene && object !== this.viewport.camera;
    }

    /**
     * 手动场景渲染
     */
    sceneGraphChanged() {
        this.viewport.render();
    }

    /**
     * 选中模型
     * @param object
     */
    objectSelected(object, needFocus: boolean = true) {
        console.log('preview objectSelected', object)
        this.viewport.selectionBox.visible = false;
        this.viewport.modules.effect.outlinePass.selectedObjects = [];

        // 漫游模式下不选中
        if (this.viewport.modules.roaming?.isRoaming) return;

        if (this.objectIsCanPick(object)) {
            if (this.viewport.modules.effect.enabled) {
                this.viewport.modules.effect.outlinePass.selectedObjects = [object];
            } else {
                this.viewport.box.setFromObject(object, true);
                if (this.viewport.box.isEmpty() === false) {
                    this.viewport.selectionBox.visible = true;
                }
            }

            if(needFocus){
                // 相机飞行
                this.objectFocused(object)
            }
        }
    }

    /**
     * 聚焦模型
     * @param object
     */
    objectFocused(object) {
        const box3 = new THREE.Box3();
        box3.setFromObject(object);

        if (box3.isEmpty()) {
            box3.set(
                new THREE.Vector3(object.position.x - 1, object.position.y - 1, object.position.z - 1), 
                new THREE.Vector3(object.position.x + 1, object.position.y + 1, object.position.z + 1)
            );
        }
        this.viewport.modules.controls.fitToBox(box3, true,{
            cover:false,
            paddingTop:3,
            paddingBottom:3,
            paddingLeft:3,
            paddingRight:3,
        });
    }

    /**
     * 聚焦查看模型
     * @param object
     * @param cameraPosition
     */
    objectFocusedView(
        object: THREE.Object3D, 
        enableTransition: boolean = true,
        customCamera?: { x?: number, y?: number, z?: number }
    ) {
        console.log("objectFocusedView",object)
        // 1. 获取对象的包围盒
        const box = new THREE.Box3();
        box.setFromObject(object);
    
        // 如果包围盒为空，创建一个默认大小的包围盒
        if (box.isEmpty()) {
            box.set(
                new THREE.Vector3(object.position.x - 1, object.position.y - 1, object.position.z - 1),
                new THREE.Vector3(object.position.x + 1, object.position.y + 1, object.position.z + 1)
            );
        }
    
        // 2. 计算包围盒的中心点和大小
        const center = box.getCenter(new THREE.Vector3());
        const size = box.getSize(new THREE.Vector3());
    
        // 3. 计算相机位置
        const distance = Math.max(size.x, size.z) * 1.5; // 根据模型大小调整距离
        const cameraPosition = new THREE.Vector3(
            customCamera?.x ? (center.x + customCamera?.x * 0.1) : (center.x + distance * 0.1),  // 使用自定义x或默认值
            customCamera?.y ? (center.y + customCamera?.y * 0.3) : (center.y + distance * 0.3),  // 使用自定义y或默认值
            customCamera?.z ? (center.z + customCamera?.z * 0.8) : (center.z + distance * 0.8)  // 使用自定义z或默认值
        );
    
        // 4. 使用CameraControls设置视角
        this.viewport.modules.controls.setLookAt(
            cameraPosition.x,
            cameraPosition.y,
            cameraPosition.z,
            center.x,
            center.y,
            center.z,
            enableTransition // 是否启用过渡动画
        );
    }


    sceneResize() {
        if (this.viewport.camera) {
            this.viewport.camera.aspect = this.viewport.container.offsetWidth / this.viewport.container.offsetHeight;
            this.viewport.camera.updateProjectionMatrix();
        }

        this.viewport.renderer.setSize(this.viewport.container.offsetWidth, this.viewport.container.offsetHeight);
        if (this.viewport.modules.effect.enabled) {
            this.viewport.modules.effect.composer.setSize(this.viewport.container.offsetWidth, this.viewport.container.offsetHeight);
            if (ViewportEffect.PassMap.has("FXAA")) {
                const FXAA = ViewportEffect.PassMap.get("FXAA") as ShaderPass;
                const pixelRatio = this.viewport.renderer.getPixelRatio();
                FXAA.material.uniforms['resolution'].value.x = 1 / (this.viewport.container.offsetWidth * pixelRatio);
                FXAA.material.uniforms['resolution'].value.y = 1 / (this.viewport.container.offsetHeight * pixelRatio);
            }
        }

        if (this.viewport.css2DRenderer) {
            this.viewport.css2DRenderer.setSize(this.viewport.container.offsetWidth, this.viewport.container.offsetHeight);
        }
        if (this.viewport.css3DRenderer){
            this.viewport.css3DRenderer.setSize(this.viewport.container.offsetWidth, this.viewport.container.offsetHeight);
        }
        
        this.viewport.render();
    };

    sceneLoadComplete() { 
        const box3 = new THREE.Box3();
        const object = this.viewport.scene;
        box3.setFromObject(object);

        if (box3.isEmpty()) {
            box3.set(
                new THREE.Vector3(object.position.x - 1, object.position.y - 1, object.position.z - 1), 
                new THREE.Vector3(object.position.x + 1, object.position.y + 1, object.position.z + 1)
            );
        }
        this.viewport.modules.controls.fitToBox(box3, true,{
            cover:false,
            paddingTop:10,
            paddingBottom:10,
            paddingLeft:10,
            paddingRight:10,
        });
    }

    dispose() { }
}